package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.extension.context.TraceContextHolder;
import com.chenfan.mcn.clients.baseinfo.*;
import com.chenfan.mcn.clients.privilege.DepartmentVO;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.clients.privilege.ScompanyRes;
import com.chenfan.mcn.component.MessageSender;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.*;
import com.chenfan.mcn.dao.*;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.common.extension.spring.TransactionUtils;
import com.chenfan.common.extension.util.SmartCompletableFuture;
import com.chenfan.common.extension.validation.groups.Add;
import com.chenfan.common.extension.validation.groups.Modify;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.service.*;
import com.chenfan.mcn.service.helper.CommonHelper;
import com.chenfan.mcn.utils.*;
import com.chenfan.process.vo.ApprovalOperationVO;
import com.chenfan.process.vo.NextNotifyVo;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: WQ
 * Date 2022/10/28
 * @描述
 */
@SuppressWarnings("AlibabaMethodTooLong")
@Service
public class DocIntentionOrderServiceImpl implements DocIntentionOrderService, ApprovalCallbackService {

    @Autowired
    private DocIntentionOrderMapper intentionOrderMapper;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private ContractExcutionOrderMapper excutionOrderMapper;

    @Autowired
    private StarBasicDataMapper starBasicDataMapper;

    @Autowired
    private StarPlatformInfoMapper starPlatformInfoMapper;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private IncomeContractService incomeContractService;

    @Autowired
    private DocIntentionOrderQuestionMapper intentionOrderQuestionMapper;

    @Autowired
    private StarRateCardService starRateCardService;

    @Autowired
    private BrandInfoService brandInfoService;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private CommonHelper commonHelper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(IntentionOrderSaveDTO saveDTO) {
        DocIntentionOrder intentionOrder = new DocIntentionOrder();
        BeanUtils.copyProperties(saveDTO, intentionOrder);
        intentionOrder.setIntentionCode(CodeGenerateHelper.getCode(BillCodeCst.INTENTION_CODE));
        intentionOrder.setActualAmount(saveDTO.getOrderAmount());
        intentionOrder.setStatus(IntentionOrderStatusEnum.DRAFT.getCode());
        intentionOrder.setRebate(saveDTO.getRebate());
        intentionOrder.setTotalIncomeAmount(saveDTO.getTotalIncomeAmount());
        intentionOrder.setActualDiscountRatio(saveDTO.getActualDiscountRatio());
        intentionOrderMapper.insert(intentionOrder);
        if(CollectionUtils.isNotEmpty(saveDTO.getQuestionList())) {
            saveDTO.getQuestionList().forEach(q -> {
                q.setId(null);
                q.setIntentionOrderId(intentionOrder.getId());
                q.setAnswer(null);
            });
            intentionOrderQuestionMapper.insertBatch(saveDTO.getQuestionList());
        }
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(intentionOrder.getId()).businessType(LogBusinessTypeEnum.INTENTION_ORDER)
                .insert(LogTemplateCst.ADD, LogBusinessTypeEnum.INTENTION_ORDER.getDesc(), intentionOrder.getIntentionCode()).build());
        return intentionOrder.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long update(IntentionOrderSaveDTO saveDTO) {
        DocIntentionOrder entity = this.getDocIntentionOrder(saveDTO.getId(), true);
        BusinessAssert.isTrue(Objects.isNull(entity.getExcutionOrderId()), "操作失败,该前置执行单已生成正式执行单,请先作废对应正式执行单!");
        LambdaUpdateWrapper<DocIntentionOrder> lambdaUpdateWrapper = Wrappers.lambdaUpdate(DocIntentionOrder.class);
        if(IntentionOrderStatusEnum.DRAFT.getCode().equals(entity.getStatus())) {
            Assert.notNull(saveDTO.getCustomerId(), "客户不能为空！");
            intentionOrderQuestionMapper.updateByNoStrategy(Wrappers.lambdaUpdate(DocIntentionOrderQuestion.class)
                    .eq(DocIntentionOrderQuestion::getIntentionOrderId, entity.getId())
                    .set(DocIntentionOrderQuestion::getIsDelete, NumberCst.ONE)
                    .set(DocIntentionOrderQuestion::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(DocIntentionOrderQuestion::getUpdateName, UserVoContextHolder.getUserName())
                    .set(DocIntentionOrderQuestion::getUpdateDate, new Date()));
            if(CollectionUtils.isNotEmpty(saveDTO.getQuestionList())) {
                saveDTO.getQuestionList().forEach(q -> {
                    q.setId(null);
                    q.setIntentionOrderId(entity.getId());
                    q.setAnswer(null);
                });
                intentionOrderQuestionMapper.insertBatch(saveDTO.getQuestionList());
            }
        } else {
            BusinessAssert.isFalse(IntentionOrderStatusEnum.anyMatch(entity.getStatus(), IntentionOrderStatusEnum.REFUSED, IntentionOrderStatusEnum.WAIT_AE_LEADER_CONFIRM,
                    IntentionOrderStatusEnum.FINNISHED, IntentionOrderStatusEnum.INVALID), McnErrorCode.INTENTION_ORDER_CAN_NOT_UPDATE);
            this.verifySaveParam(saveDTO);
            if(IntentionOrderStatusEnum.anyMatch(entity.getStatus(), IntentionOrderStatusEnum.REJECTED, IntentionOrderStatusEnum.CONRIMED,
                    IntentionOrderStatusEnum.EXECUTING, IntentionOrderStatusEnum.EXECUTED)) {
                lambdaUpdateWrapper.set(DocIntentionOrder::getStatus, IntentionOrderStatusEnum.WAIT_AE_LEADER_CONFIRM.getCode());
            }
        }
        intentionOrderMapper.updateByNoStrategy(lambdaUpdateWrapper
                .eq(DocIntentionOrder::getId, entity.getId())
                .set(DocIntentionOrder::getCustomerId, saveDTO.getCustomerId())
                .set(DocIntentionOrder::getStarId, saveDTO.getStarId())
                .set(DocIntentionOrder::getStarPlatformInfoId, saveDTO.getStarPlatformInfoId())
                .set(DocIntentionOrder::getProductName, saveDTO.getProductName())
                .set(DocIntentionOrder::getCooperateBrand, saveDTO.getCooperateBrand())
                .set(DocIntentionOrder::getPublishForm, saveDTO.getPublishForm())
                .set(DocIntentionOrder::getPublishDate, saveDTO.getPublishDate())
                .set(DocIntentionOrder::getPublishDateEnd, saveDTO.getPublishDateEnd())
                .set(DocIntentionOrder::getHaveLinkCommand, saveDTO.getHaveLinkCommand())
                .set(DocIntentionOrder::getFromMicroTask, saveDTO.getFromMicroTask())
                .set(DocIntentionOrder::getOrderAmount, saveDTO.getOrderAmount())
                .set(DocIntentionOrder::getCardRatePrice, saveDTO.getCardRatePrice())
                .set(DocIntentionOrder::getActualAmount, saveDTO.getOrderAmount())
                .set(DocIntentionOrder::getOtherIncomeAmount, saveDTO.getOtherIncomeAmount())
                .set(DocIntentionOrder::getOtherIncomeRemark, saveDTO.getOtherIncomeRemark())
                .set(DocIntentionOrder::getPlatformFeeAmount, saveDTO.getPlatformFeeAmount())
                .set(DocIntentionOrder::getSpecialIncomeAmount, saveDTO.getSpecialIncomeAmount())
                .set(DocIntentionOrder::getSpecialIncomeRemark, saveDTO.getSpecialIncomeRemark())
                .set(DocIntentionOrder::getSubsidyIncomeAmount, saveDTO.getSubsidyIncomeAmount())
                .set(DocIntentionOrder::getSubsidyIncomeRemark, saveDTO.getSubsidyIncomeRemark())
                .set(DocIntentionOrder::getTotalIncomeAmount, saveDTO.getTotalIncomeAmount())
                .set(DocIntentionOrder::getRebate, saveDTO.getRebate())
                .set(DocIntentionOrder::getRebateAmount, saveDTO.getRebateAmount())
                .set(DocIntentionOrder::getActualDiscountRatio, saveDTO.getActualDiscountRatio())
                .set(DocIntentionOrder::getExcutorId, saveDTO.getExcutorId())
                .set(DocIntentionOrder::getExcutorName, saveDTO.getExcutorName())
                .set(DocIntentionOrder::getStarAgentId, saveDTO.getStarAgentId())
                .set(DocIntentionOrder::getStarAgentName, saveDTO.getStarAgentName())
                .set(DocIntentionOrder::getRemark, saveDTO.getRemark())
                .set(DocIntentionOrder::getIsLiveAd, saveDTO.getIsLiveAd())
                .set(DocIntentionOrder::getHaveDiscountApproval, saveDTO.getHaveDiscountApproval())
                .set(DocIntentionOrder::getDiscountScreenshot, saveDTO.getDiscountScreenshot())
                .set(DocIntentionOrder::getUpdateBy, UserVoContextHolder.getUserId())
                .set(DocIntentionOrder::getUpdateName, UserVoContextHolder.getUserName())
                .set(DocIntentionOrder::getUpdateDate, new Date()));
        //提起审批流程
        if(IntentionOrderStatusEnum.anyMatch(entity.getStatus(), IntentionOrderStatusEnum.REJECTED, IntentionOrderStatusEnum.CONRIMED,
                IntentionOrderStatusEnum.EXECUTING, IntentionOrderStatusEnum.EXECUTED)) {
            approvalFlowService.startProcess(entity.getId(), entity.getIntentionCode(), ApprovalEnum.INTENTION_ORDER_AE, JSON.toJSONString(entity));
        }
        if (IntentionOrderStatusEnum.anyMatch(entity.getStatus(), IntentionOrderStatusEnum.EXECUTING, IntentionOrderStatusEnum.WAIT_AE_LEADER_CONFIRM)) {
            // 给执行人&经纪人&创建人发送消息提醒
            List<Long> targets = Arrays.asList(saveDTO.getExcutorId(),saveDTO.getStarAgentId(),entity.getCreateBy());
            Map<String, String> param = new HashMap<>(16);
            param.put("updateName", UserVoContextHolder.getUserName());
            param.put("code", entity.getIntentionCode());
            param.put("time", DateUtil.getTimeStr(saveDTO.getPublishDate(), "yyyy-MM-dd"));
            param.put("productName", saveDTO.getProductName());
            StarBasicData starBasicData = starBasicDataMapper.selectById(entity.getStarId());
            param.put("starName", starBasicData.getStarNickname());
            param.put("businessId", entity.getId().toString());
            messageSender.sendNotify(CommentBusinessTypeEnum.INTENTION_ORDER, UserVoContextHolder.getTenantId(), MsgCenterTemplateCst.INTENTION_ORDER,targets, param);
        }
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                .businessType(LogBusinessTypeEnum.INTENTION_ORDER)
                .compare(entity, intentionOrderMapper.selectById(entity.getId()))
                .build());
        return entity.getId();
    }


    @Override
    public IntentionOrderDetailVO detail(Long id, Boolean showTab) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(id, true);
        IntentionOrderDetailVO detailVO = new IntentionOrderDetailVO();
        BeanUtils.copyProperties(docIntentionOrder, detailVO);
        detailVO.setQuestionList(intentionOrderQuestionMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrderQuestion.class)
                .eq(DocIntentionOrderQuestion::getIntentionOrderId, docIntentionOrder.getId())
                .eq(DocIntentionOrderQuestion::getIsDelete, NumberCst.ZERO)));
        if(showTab && Objects.nonNull(docIntentionOrder.getIncomeContractId())) {
            IntentionOrderDetailVO.IncomeContractTab incomeContractTab = new IntentionOrderDetailVO.IncomeContractTab();
            incomeContractTab.setIncomeContractId(docIntentionOrder.getIncomeContractId());
            incomeContractTab.setIncomeContractCode(docIntentionOrder.getIncomeContractCode());
            IncomeContract incomeContract = incomeContractMapper.selectById(docIntentionOrder.getIncomeContractId());
            if(Objects.nonNull(incomeContract)) {
                Long flowId = approvalFlowService.getFlowId(incomeContract.getId(), ApprovalEnum.getEnumByContractType(incomeContract.getContractType()).getProcessId());
                incomeContractTab.setApprovalStatus(ApprovalStatusEnum.getStatusName(incomeContract.getApprovalStatus()));
                JSONObject flowMapping = approvalFlowService.getFlowStatus(Lists.newArrayList(flowId));
                incomeContractTab.setFlowStatus(CommonUtil.defaultString(flowMapping, flowId));
                incomeContractTab.setArchivingStatus(ArchivingStatusEnum.getStatusName(incomeContract.getArchivingStatus()));
                incomeContractTab.setBusinessAmount(incomeContract.getBusinessAmount());
            }

            detailVO.setIncomeContractTab(incomeContractTab);
        }
        if(showTab && Objects.nonNull(docIntentionOrder.getExcutionOrderId())) {
            IntentionOrderDetailVO.ExcutionOrderTab excutionOrderTab = new IntentionOrderDetailVO.ExcutionOrderTab();
            excutionOrderTab.setExcutionOrderId(docIntentionOrder.getExcutionOrderId());
            excutionOrderTab.setExcutionOrderCode(docIntentionOrder.getExcutionOrderCode());
            ContractExcutionOrder contractExcutionOrder = excutionOrderMapper.selectById(docIntentionOrder.getExcutionOrderId());
            if(Objects.nonNull(contractExcutionOrder)) {
                Long flowId = approvalFlowService.getFlowId(contractExcutionOrder.getId(), ApprovalEnum.getEnumByExcutionOrderType(contractExcutionOrder.getType()).getProcessId());
                excutionOrderTab.setApprovalStatus(ExcutionApprovalStatusEnum.getStatusName(contractExcutionOrder.getApprovalStatus()));
                excutionOrderTab.setFlowStatus(CommonUtil.defaultString(approvalFlowService.getFlowStatus(Lists.newArrayList(flowId)), flowId));
                excutionOrderTab.setActualQuotedPrice(contractExcutionOrder.getActualQuotedPrice());
            }
            detailVO.setExcutionOrderTab(excutionOrderTab);
        }
        CommonUtil.defaultMap(RpcUtil.getObjException(baseInfoClient.getMcnCustomerByIds(Lists.newArrayList(detailVO.getCustomerId())), "获取MCN客户档案信息错误！")).entrySet().forEach(e -> {
            if(Objects.nonNull(e.getValue())) {
                detailVO.setCustomerName(e.getValue().getCustomerNameC());
            }
        });
        //查红人基础资料
        StarBasicData starBasicData = starBasicDataMapper.selectById(docIntentionOrder.getStarId());
        if(Objects.nonNull(starBasicData)) {
            detailVO.setStarNickname(starBasicData.getStarNickname());
            detailVO.setStarName(starBasicData.getStarName());
        }
        //查询红人平台信息
        StarPlatformInfo starPlatformInfo = starPlatformInfoMapper.selectById(docIntentionOrder.getStarPlatformInfoId());
        if(Objects.nonNull(starPlatformInfo)) {
            detailVO.setPlatformId(starPlatformInfo.getPlatformId());
            detailVO.setPlatformName(starPlatformInfo.getPlatformName());
            detailVO.setPlatNickName(starPlatformInfo.getPlatNickName());
            detailVO.setContractingId(starPlatformInfo.getContractingId());
            if(Objects.nonNull(detailVO.getContractingId())) {
                //我司合同主体
                Map<Long, String> companyMap = CommonUtil.defaultList(privilegeClient.getParList().getObj()).
                        stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
                detailVO.setCompanyContractSubject(companyMap.get(detailVO.getContractingId()));
            }
        }
        detailVO.setCooperateBrandName(brandInfoService.getBrandNameByCode(detailVO.getCooperateBrand()));
        Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
        detailVO.setPublishFormName(this.getPublishFormName(publishFormDictMap, detailVO.getPlatformId(), detailVO.getPublishForm()));
        detailVO.setStatusName(IntentionOrderStatusEnum.getStatusName(detailVO.getStatus()));
        //审批流信息
        Long flowId = approvalFlowService.getFlowId(id, ApprovalEnum.INTENTION_ORDER_AE.getProcessId());
        if (Objects.nonNull(flowId)) {
            detailVO.setFlowId(flowId);
            List<Long> flowList = new ArrayList<>(Collections.singletonList(flowId));
            JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
            detailVO.setFlowStatusName(CommonUtil.defaultString(flowMapping, detailVO.getFlowId()));
        }
        String stringFlowIds = approvalFlowService.getStringFlowIds(id, ApprovalEnum.INTENTION_ORDER_AE.getProcessId());
        detailVO.setFlowIds(stringFlowIds);
        //查询执行人部门主管信息
        if(Objects.nonNull(detailVO.getExcutorId())) {
            Map<Long, DepartmentVO> departmentVoMap = privilegeClient.getDepartmentHeadByUserIds(Arrays.asList(detailVO.getExcutorId())).getObj();
            if(CommonUtil.containsKey(departmentVoMap, detailVO.getExcutorId())) {
                DepartmentVO departmentVO = departmentVoMap.get(detailVO.getExcutorId());
                detailVO.setExcutorLeaderId(departmentVO.getDepartmentHeadId());
                detailVO.setExcutorLeaderName(departmentVO.getDepartmentHeadName());
            }
        }
        return detailVO;
    }

    @Override
    public List<IntentionOrderDetailVO> batchDetail(List<Long> idList) {
        List<DocIntentionOrder> dataList = intentionOrderMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrder.class)
                .in(DocIntentionOrder::getId, idList).eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO).orderByDesc(DocIntentionOrder::getCreateDate));
        BusinessAssert.notEmpty(dataList, McnErrorCode.DATA_NOT_FOUND, "前置执行单都查询不到");
        Map<Long, List<DocIntentionOrderQuestion>> questionMap = CommonUtil.defaultList(intentionOrderQuestionMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrderQuestion.class)
                .in(DocIntentionOrderQuestion::getIntentionOrderId, dataList.stream().map(DocIntentionOrder::getId).collect(Collectors.toList()))
                .eq(DocIntentionOrderQuestion::getIsDelete, NumberCst.ZERO))).stream().collect(Collectors.groupingBy(DocIntentionOrderQuestion::getIntentionOrderId));
        List<IntentionOrderDetailVO> voList = dataList.stream().map(e -> {
            IntentionOrderDetailVO detailVO = new IntentionOrderDetailVO();
            BeanUtils.copyProperties(e, detailVO);
            detailVO.setQuestionList(questionMap.get(detailVO.getId()));
            return detailVO;
        }).collect(Collectors.toList());
        List<Long> starIdList =  voList.stream().map(e -> e.getStarId()).distinct().collect(Collectors.toList());
        List<Long> customerIdList =  voList.stream().map(e -> e.getCustomerId()).distinct().collect(Collectors.toList());
        List<Long> starPlatformInfoIdList =  voList.stream().map(e -> e.getStarPlatformInfoId()).distinct().collect(Collectors.toList());
        //查询客户数据
        Map<Long, String> customerMap = new HashMap<>(customerIdList.size());
        CommonUtil.defaultMap(RpcUtil.getObjException(baseInfoClient.getMcnCustomerByIds(customerIdList), "获取MCN客户档案信息错误！")).entrySet().forEach(e -> {
            if(Objects.nonNull(e.getValue())) {
                customerMap.putIfAbsent(e.getKey(), e.getValue().getCustomerNameC());
            }
        });
        //查询红人与红人平台数据
        Map<Long, StarBasicData> starMap = CommonUtil.defaultList(starBasicDataMapper.selectBatchIds(starIdList)).stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
        Map<Long, StarPlatformInfo> starPlatformMap = CommonUtil.defaultList(starPlatformInfoMapper.selectBatchIds(starPlatformInfoIdList)).stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
        //我司合同主体
        Map<Long, String> companyMap = CommonUtil.defaultList(privilegeClient.getParList().getObj()).
                stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
        //
        Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
        List<String> brandCodes = voList.stream().map(IntentionOrderDetailVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
        voList.forEach(detailVO -> {
            detailVO.setStatusName(IntentionOrderStatusEnum.getStatusName(detailVO.getStatus()));
            if(customerMap.containsKey(detailVO.getCustomerId())) {
                detailVO.setCustomerName(customerMap.get(detailVO.getCustomerId()));
            }
            if(starMap.containsKey(detailVO.getStarId())) {
                StarBasicData starBasicData = starMap.get(detailVO.getStarId());
                detailVO.setStarNickname(starBasicData.getStarNickname());
                detailVO.setStarName(starBasicData.getStarName());
            }
            if(starPlatformMap.containsKey(detailVO.getStarPlatformInfoId())) {
                StarPlatformInfo starPlatformInfo = starPlatformMap.get(detailVO.getStarPlatformInfoId());
                detailVO.setPlatformId(starPlatformInfo.getPlatformId());
                detailVO.setPlatformName(starPlatformInfo.getPlatformName());
                detailVO.setPlatNickName(starPlatformInfo.getPlatNickName());
                detailVO.setContractingId(starPlatformInfo.getContractingId());
                if(Objects.nonNull(detailVO.getContractingId()) && CommonUtil.containsKey(companyMap, detailVO.getContractingId())) {
                    detailVO.setCompanyContractSubject(companyMap.get(detailVO.getContractingId()));
                }
            }
            detailVO.setPublishFormName(this.getPublishFormName(publishFormDictMap, detailVO.getPlatformId(), detailVO.getPublishForm()));
            if(brandMap.containsKey(detailVO.getCooperateBrand())) {
                detailVO.setCooperateBrandName(brandMap.get(detailVO.getCooperateBrand()));
            }
        });
        return voList;
    }

    @Override
    public Page<IntentionOrderListVO> page(McnPage<IntentionOrderListVO> mcnPage, IntentionOrderSearchDTO searchDTO) {
        mcnPage.setPageNum(searchDTO.getPageNum());
        mcnPage.setPageSize(searchDTO.getPageSize());
        searchDTO.setAlias("dio.");
        Page<IntentionOrderListVO> result = intentionOrderMapper.getIntentionOrderPage(mcnPage,searchDTO);
        List<IntentionOrderListVO> records = result.getRecords();
        if(CollectionUtils.isNotEmpty(records)) {
            //查询客户信息
            List<Long> customerIdList = records.stream().map(IntentionOrderListVO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList),
                    () -> baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
            //查询平台信息
            List<Long> platIds = records.stream().map(IntentionOrderListVO::getStarPlatformInfoId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, StarPlatInfoVO> platInfoMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(platIds), () -> CommonUtil.defaultList(starPlatformInfoMapper.getByIds(platIds))
                    .stream().collect(Collectors.toMap(StarPlatInfoVO::getId, Function.identity(), (x, y) -> x)), Collections.EMPTY_MAP);
            //查询红人信息
            List<Long> startIds = records.stream().map(IntentionOrderListVO::getStarId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, StarBasicData> starBasicDataMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(platIds), () -> CommonUtil.defaultList(starBasicDataMapper.selectBatchIds(startIds))
                    .stream().collect(Collectors.toMap(StarBasicData::getId, Function.identity(), (x, y) -> x)), Collections.EMPTY_MAP);
            Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
            List<String> brandCodes = records.stream().map(IntentionOrderListVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            for(IntentionOrderListVO record : records) {
                BaseCustomer baseCustomer = CommonUtil.getMapValue(customerMap, record.getCustomerId());
                StarPlatInfoVO starPlatInfoVO = CommonUtil.getMapValue(platInfoMap, record.getStarPlatformInfoId());
                StarBasicData starBasicData = CommonUtil.getMapValue(starBasicDataMap, record.getStarId());
                if(baseCustomer != null) {
                    record.setCustomerName(baseCustomer.getCustomerNameC());
                }
                if(starPlatInfoVO != null) {
                    record.setPlatformId(starPlatInfoVO.getPlatformId());
                    record.setStartPlatformInfoName(starPlatInfoVO.getPlatformName());
                    record.setPlatNickName(starPlatInfoVO.getPlatNickName());
                    record.setPublishFormName(this.getPublishFormName(publishFormDictMap, record.getPlatformId(), record.getPublishForm()));
                }
                if(starBasicData != null){
                    record.setStarName(starBasicData.getStarNickname());
                }
                if(brandMap.containsKey(record.getCooperateBrand())) {
                    record.setCooperateBrandName(brandMap.get(record.getCooperateBrand()));
                }
            }
        }
        return result;
    }

    @Override
    public List<IntentionOrderExportVO> export(IntentionOrderSearchDTO searchDTO) {
        searchDTO.setAlias("dio.");
        List<IntentionOrderExportVO> records = intentionOrderMapper.exportIntentionOrder(searchDTO);
        if (CollectionUtils.isNotEmpty(records)) {
            //查询客户信息
            List<Long> customerIdList = records.stream().map(IntentionOrderExportVO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList),
                    () -> baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
            //查询平台信息
            List<Long> platIds = records.stream().map(IntentionOrderExportVO::getStarPlatformInfoId).filter(Objects::nonNull).collect(Collectors.toList());
            Map<Long, StarPlatInfoVO> platInfoMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(platIds), () -> CommonUtil.defaultList(starPlatformInfoMapper.getByIds(platIds))
                            .stream().collect(Collectors.toMap(StarPlatInfoVO::getId, Function.identity(), (x, y) -> x)), Collections.EMPTY_MAP);
            Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
            List<String> brandCodes = records.stream().map(IntentionOrderExportVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            for(IntentionOrderExportVO record : records) {
                record.setStatusName(IntentionOrderStatusEnum.getStatusName(record.getStatus()));
                BaseCustomer baseCustomer = CommonUtil.getMapValue(customerMap, record.getCustomerId());
                StarPlatInfoVO starPlatInfoVO = CommonUtil.getMapValue(platInfoMap, record.getStarPlatformInfoId());
                if(baseCustomer != null) {
                    record.setCustomerName(baseCustomer.getCustomerNameC());
                }
                if(starPlatInfoVO != null) {
                    record.setPlatformId(starPlatInfoVO.getPlatformId());
                    record.setPlatformName(starPlatInfoVO.getPlatformName());
                    record.setPlatNickName(starPlatInfoVO.getPlatNickName());
                    record.setPublishFormName(this.getPublishFormName(publishFormDictMap, record.getPlatformId(), record.getPublishForm()));
                }
                if(brandMap.containsKey(record.getCooperateBrand())) {
                    record.setCooperateBrandName(brandMap.get(record.getCooperateBrand()));
                }
            }
        }
        return records;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long changeStatus(IntentionOrderStatusEnum statusEnum, Long id, boolean confirmDiff) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(id, true);
        BusinessAssert.isFalse(IntentionOrderStatusEnum.INVALID.getCode().equals(docIntentionOrder.getStatus()),
                McnErrorCode.BUSINESS_ERROR, "该前置执行单已作废");
        LambdaUpdateWrapper<DocIntentionOrder> lambdaUpdateWrapper =  Wrappers.lambdaUpdate(DocIntentionOrder.class).eq(DocIntentionOrder::getId, id);
        switch (statusEnum) {
            case DRAFT:
                //撤回操作 到草稿状态
                BusinessAssert.isTrue(IntentionOrderStatusEnum.isAeLeaderConfirm(docIntentionOrder.getStatus()), "非审批中不允许撤回");
                approvalFlowService.revokeProcess(docIntentionOrder.getId(), ApprovalEnum.INTENTION_ORDER_AE.getProcessId());
                TraceContextHolder.putActionName("撤回");
                break;
            case WAIT_ACCEPT:
                //提交 直接跳到待AE主管确认
                BusinessAssert.isTrue(IntentionOrderStatusEnum.anyMatch(docIntentionOrder.getStatus(), IntentionOrderStatusEnum.DRAFT),
                        McnErrorCode.BUSINESS_ERROR, "非草稿-不允许提交");
                IntentionOrderSaveDTO saveDTO = new IntentionOrderSaveDTO();
                BeanUtils.copyProperties(docIntentionOrder, saveDTO);
                this.verifySaveParam(saveDTO);
                if(confirmDiff) {
                    saveDTO.setCardRatePrice(this.getRateCardPrice(docIntentionOrder));
                    lambdaUpdateWrapper.set(DocIntentionOrder::getCardRatePrice, saveDTO.getCardRatePrice())
                            .set(DocIntentionOrder::getActualDiscountRatio, saveDTO.getActualDiscountRatio());
                } else  {
                    BigDecimal oldRateCardPrice = ObjectUtils.defaultIfNull(docIntentionOrder.getCardRatePrice(), BigDecimal.ZERO);
                    BigDecimal newRateCardPrice = ObjectUtils.defaultIfNull(this.getRateCardPrice(docIntentionOrder), BigDecimal.ZERO);
                    if(oldRateCardPrice.compareTo(newRateCardPrice) != 0) {
                        return id;
                    }
                }
                //提交跳过接单/拒单等状态
                statusEnum = IntentionOrderStatusEnum.WAIT_AE_LEADER_CONFIRM;
                TraceContextHolder.putActionName("提交");
                break;
            //AE确认执行
            case EXECUTING:
                if(Objects.isNull(docIntentionOrder.getExecuteTime())) {
                    lambdaUpdateWrapper.set(DocIntentionOrder::getExecuteTime, new Date());
                }
                BusinessAssert.isTrue(IntentionOrderStatusEnum.CONRIMED.getCode().equals(docIntentionOrder.getStatus()),
                        McnErrorCode.BUSINESS_ERROR, "非已确认-不允许执行");
                commonHelper.verifyExcutorAuth(docIntentionOrder.getExcutorId(), false);
                TraceContextHolder.putActionName("执行");
                break;
            //执行完成
            case EXECUTED:
                BusinessAssert.isTrue(IntentionOrderStatusEnum.EXECUTING.getCode().equals(docIntentionOrder.getStatus()),
                        McnErrorCode.BUSINESS_ERROR, "非执行中-不允许执行完成");
                TraceContextHolder.putActionName("执行完成");
                break;
            //作废
            case INVALID:
                BusinessAssert.isTrue(Objects.isNull(docIntentionOrder.getExcutionOrderId()), "作废失败,该前置执行单已生成正式执行单,请先作废对应正式执行单!");
                BusinessAssert.isFalse(IntentionOrderStatusEnum.anyMatch(docIntentionOrder.getStatus(), IntentionOrderStatusEnum.REFUSED, IntentionOrderStatusEnum.FINNISHED),
                        McnErrorCode.BUSINESS_ERROR, "已拒单/已完结-不允许作废");
                TraceContextHolder.putActionName("作废");
                break;
            default:
                throw new BusinessException(McnErrorCode.DATA_OPERATION_NOT_SUPPORTED);
        }
        //作废的话，释放前置执行单与收入合同、正式执行单的关联关系
        if(IntentionOrderStatusEnum.isInvalid(statusEnum.getCode())) {
            lambdaUpdateWrapper.set(DocIntentionOrder::getExcutionOrderId, null).set(DocIntentionOrder::getExcutionOrderCode, null);
        }
        intentionOrderMapper.updateByNoStrategy(lambdaUpdateWrapper
                .set(DocIntentionOrder::getStatus, statusEnum.getCode())
                .set(DocIntentionOrder::getUpdateBy, UserVoContextHolder.getUserId())
                .set(DocIntentionOrder::getUpdateName, UserVoContextHolder.getUserName())
                .set(DocIntentionOrder::getUpdateDate, new Date()));
        //提交时-提起审批流-避免重复提起审批
        if(IntentionOrderStatusEnum.isAeLeaderConfirm(statusEnum.getCode())) {
            approvalFlowService.startProcess(docIntentionOrder.getId(), docIntentionOrder.getIntentionCode(), ApprovalEnum.INTENTION_ORDER_AE, JSON.toJSONString(docIntentionOrder));
        } else if(IntentionOrderStatusEnum.isAeLeaderConfirm(docIntentionOrder.getStatus())
                && IntentionOrderStatusEnum.isInvalid(statusEnum.getCode())) {
            //待AE主管确认时作废审批流
            approvalFlowService.revokeProcess(docIntentionOrder.getId(), ApprovalEnum.INTENTION_ORDER_AE.getProcessId());
        }
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(id)
                .businessType(LogBusinessTypeEnum.INTENTION_ORDER)
                .compare(docIntentionOrder, intentionOrderMapper.selectById(id))
                .build());
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long addContract(IntentionOrderAddContractDTO addContractDTO) {
        List<DocIntentionOrder> dataList = intentionOrderMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrder.class)
                .in(DocIntentionOrder::getId, addContractDTO.getIdList())
                .eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notEmpty(dataList, McnErrorCode.DATA_NOT_FOUND);
        List<Long> customerIdList = dataList.stream().map(DocIntentionOrder::getCustomerId).distinct().collect(Collectors.toList());
        BusinessAssert.isTrue(customerIdList.size() == 1, McnErrorCode.BUSINESS_ERROR, "请选择客户相同的前置执行单创建合同！");
        dataList.forEach(data -> {
            BusinessAssert.isTrue(IntentionOrderStatusEnum.anyMatch(data.getStatus(), IntentionOrderStatusEnum.EXECUTING, IntentionOrderStatusEnum.EXECUTED),
                    McnErrorCode.BUSINESS_ERROR, "【"+ data.getIntentionCode() + "】仅允许【执行中】、【执行完成】状态前置执行单可创建合同！");
            BusinessAssert.isNull(data.getIncomeContractId(), McnErrorCode.BUSINESS_ERROR, "【"+ data.getIntentionCode() + "】已创建收入合同或者正式执行单，请勿重复创建！");
        });
        BigDecimal totalCardRatePrice = dataList.stream().map(DocIntentionOrder::getCardRatePrice).filter(x -> Objects.nonNull(x)).reduce(BigDecimal.ZERO, BigDecimal::add);
        DocIntentionOrder maxIntentionOrder = dataList.stream().sorted(Comparator.comparing(DocIntentionOrder::getOrderAmount).reversed()).findFirst().get();
        IncomeContractAddDTO incomeContractAddDTO = new IncomeContractAddDTO();
        incomeContractAddDTO.setContractType(addContractDTO.getContractType());
        incomeContractAddDTO.setCustomerId(customerIdList.get(0));
        incomeContractAddDTO.setTotalAmount(totalCardRatePrice);
        if(IncomeContractTypeEnum.isLiveContract(addContractDTO.getContractType())) {
            incomeContractAddDTO.setCooperationType(CooperationTypeEnum.ONLINE_STRAIGHT_COMMISSION.getCode());
            incomeContractAddDTO.setContainsAdvertising(NumberCst.ONE);
        }
        incomeContractAddDTO.setCooperateProduct(maxIntentionOrder.getProductName());
        incomeContractAddDTO.setCooperateBrand(maxIntentionOrder.getCooperateBrand());
        incomeContractAddDTO.setApprovalStatus(ApprovalStatusEnum.UN_COMMIT.getCode());
        incomeContractAddDTO.setPlatformOrders(Objects.nonNull(dataList.get(0).getFromMicroTask()) && Integer.valueOf(0).equals(dataList.get(0).getFromMicroTask()) ? Boolean.FALSE : Boolean.TRUE);
        incomeContractAddDTO.setBusinessAmount(dataList.stream().map(x -> x.getTotalIncomeAmount()).filter(x -> Objects.nonNull(x)).reduce(BigDecimal.ZERO, BigDecimal::add));
        List<Long> starIdList =  dataList.stream().map(e -> e.getStarId()).distinct().collect(Collectors.toList());
        Map<Long, StarBasicData> starMap = CommonUtil.defaultList(starBasicDataMapper.selectBatchIds(starIdList)).stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
        List<Long> starPlatformInfoIdList =  dataList.stream().map(e -> e.getStarPlatformInfoId()).distinct().collect(Collectors.toList());
        Map<Long, StarPlatformInfo> starPlatformMap = CommonUtil.defaultList(starPlatformInfoMapper.selectBatchIds(starPlatformInfoIdList))
                .stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
        List<ContractExcutionOrder> excutionOrderList = new ArrayList<>(dataList.size());
        dataList.forEach(data -> {
            ContractExcutionOrder excutionOrder = new ContractExcutionOrder();
            BeanUtils.copyProperties(data,excutionOrder,ContractExcutionOrder.class);
            excutionOrder.setId(null);
            excutionOrder.setIntentionOrderId(data.getId());
            excutionOrder.setStarId(data.getStarId());
            StarBasicData starBasicData = starMap.get(data.getStarId());
            BusinessAssert.notNull(starBasicData, McnErrorCode.DATA_NOT_FOUND, "【"+ data.getIntentionCode() + "】查询不到红人信息！");
            StarPlatformInfo starPlatformInfo = starPlatformMap.get(data.getStarPlatformInfoId());
            excutionOrder.setRealAmount(data.getCardRatePrice());
            excutionOrder.setCardRatePrice(data.getCardRatePrice());
            excutionOrder.setOtherAmount(data.getOtherIncomeAmount());
            excutionOrder.setOtherAmountRemark(data.getOtherIncomeRemark());
            excutionOrder.setOtherFee(data.getSpecialIncomeAmount());
            excutionOrder.setSpecialFeeRemark(data.getSpecialIncomeRemark());
            excutionOrder.setSubsidyIncomeAmount(data.getSubsidyIncomeAmount());
            excutionOrder.setSubsidyIncomeRemark(data.getSubsidyIncomeRemark());
            excutionOrder.setRealAmount(data.getOrderAmount());
            excutionOrder.setActualQuotedPrice(data.getTotalIncomeAmount());
            excutionOrder.setActualDiscountRatio(data.getActualDiscountRatio());
            excutionOrder.setPlatformFee(data.getPlatformFeeAmount());
            if(StarTypeEnum.INSIDE.getCode().equals(starBasicData.getStarType())) {
                excutionOrder.setType(ExcutionOrderTypeEnum.INSIDE_EXCUTION_ORDER.getType());
                excutionOrder.setMicroTaskAmount(BigDecimal.ZERO);
                excutionOrder.setFansHeadlineAmount(BigDecimal.ZERO);
                if(Objects.nonNull(starPlatformInfo)) {
                    excutionOrder.setDividedRate(starPlatformInfo.getDevidedRate());
                }
            } else if(StarTypeEnum.OUTSIDE.getCode().equals(starBasicData.getStarType())) {
                excutionOrder.setType(ExcutionOrderTypeEnum.OUTSIDE_EXCUTION_ORDER.getType());
            } else if(StarTypeEnum.KOC.getCode().equals(starBasicData.getStarType())) {
                excutionOrder.setType(ExcutionOrderTypeEnum.KOC_EXCUTION_ORDER.getType());
            } else {
                throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(), "【"+ data.getIntentionCode() + "】无法识别对应的正式执行单类型！");
            }
            excutionOrder.setPlatformReport(Integer.valueOf(0).equals(data.getFromMicroTask()) ? Boolean.FALSE : Boolean.TRUE);
            excutionOrder.setStarNickName(Optional.ofNullable(starPlatformInfo).map(x -> x.getPlatNickName()).orElse(null));
            excutionOrder.setStarPlatformInfoId(data.getStarPlatformInfoId());
            excutionOrder.setHaveLinkCommand(data.getHaveLinkCommand());
            excutionOrder.setPromisePublishDate(data.getPublishDate());
            excutionOrder.setPromisePublishDateEnd(data.getPublishDateEnd());
            excutionOrder.setPublishForm(data.getPublishForm());
            excutionOrder.setPlatformOrderCode("");
            excutionOrder.setCategory("");
            excutionOrder.setBrandName(data.getCooperateBrand());
            excutionOrder.setProductName(data.getProductName());
            excutionOrder.setExcutorId(data.getExcutorId());
            excutionOrder.setExcutorName(data.getExcutorName());
            excutionOrder.setAeCustomerRabateRate(data.getRebate());
            excutionOrder.setAeCustomerRabateAmount(data.getRebateAmount());
            excutionOrderList.add(excutionOrder);
        });
        incomeContractAddDTO.setExcutionOrders(excutionOrderList);
        incomeContractAddDTO.setIsFromExcutionOrder(true);
        ValidatorUtil.validate(incomeContractAddDTO, Add.class);
        Long incomeContractId = incomeContractService.addIncomeContract(incomeContractAddDTO);
        excutionOrderList.forEach(excutionOrder -> {
            DocIntentionOrder updateIntentionOrder = new DocIntentionOrder();
            updateIntentionOrder.setId(excutionOrder.getIntentionOrderId());
            updateIntentionOrder.setIncomeContractId(excutionOrder.getIncomeContractId());
            updateIntentionOrder.setIncomeContractCode(excutionOrder.getIncomeContractCode());
            updateIntentionOrder.setExcutionOrderId(excutionOrder.getId());
            updateIntentionOrder.setExcutionOrderCode(excutionOrder.getExcuteCode());
            intentionOrderMapper.updateById(updateIntentionOrder);
        });
        return incomeContractId;
    }

    @Override
    public AnchorSchedulingCalendarVO anchorScheduling(AnchorSchedulingSearchDTO searchDTO) {
        searchDTO.setAlias("a.");
        List<DocIntentionOrder> dataList = intentionOrderMapper.getAnchorSchedulingData(searchDTO);
        if(CollectionUtils.isEmpty(dataList)) {
            return AnchorSchedulingCalendarVO.defaultAnchorSchedulingCalendarVO(searchDTO.getMonth());
        }
        List<Long> starIdList =  dataList.stream().map(e -> e.getStarId()).distinct().collect(Collectors.toList());
        List<Long> customerIdList =  dataList.stream().map(e -> e.getCustomerId()).distinct().collect(Collectors.toList());
        List<Long> starPlatformInfoIdList =  dataList.stream().map(e -> e.getStarPlatformInfoId()).distinct().collect(Collectors.toList());
        AnchorSchedulingCalendarVO vo = new AnchorSchedulingCalendarVO();
        List<CompletableFuture> completableFutureList = new ArrayList<>(4);
        //获取订单总金额
        completableFutureList.add(SmartCompletableFuture.runAsync(() -> vo.setTotalOrderAmount(intentionOrderMapper.getTotalOrderAmount(searchDTO))));
        //按状态计数
        completableFutureList.add(SmartCompletableFuture.runAsync(() -> {
            Map<Integer, IntentionOrderStatusSummaryVO> statusSummaryMap = CommonUtil.defaultList(intentionOrderMapper.getStatusSummaryList(searchDTO)).stream().collect(Collectors.toMap(k -> k.getStatus(), Function.identity()));
            for(IntentionOrderStatusEnum statusEnum : IntentionOrderStatusEnum.values()) {
                if(!statusSummaryMap.containsKey(statusEnum.getCode())) {
                    statusSummaryMap.put(statusEnum.getCode(), new IntentionOrderStatusSummaryVO(statusEnum.getCode(), 0L));
                }
            }
            vo.setStatusSummaryList(statusSummaryMap.values());
        }));
        //查询客户数据
        Map<Long, BaseCustomer> customerMap = new HashMap<>(customerIdList.size());
        completableFutureList.add(SmartCompletableFuture.runAsync(() ->
            CommonUtil.defaultMap(RpcUtil.getObjException(baseInfoClient.getMcnCustomerByIds(customerIdList), "获取MCN客户档案信息错误！")).entrySet().forEach(e -> {
                if(Objects.nonNull(e.getValue())) {
                    customerMap.putIfAbsent(e.getKey(), e.getValue());
                }
            })
        ));
        //查询红人与红人平台数据
        Map<Long, StarBasicData> starMap = new HashMap<>(starIdList.size());
        Map<Long, StarPlatformInfo> starPlatformMap = new HashMap<>(starPlatformInfoIdList.size());
        completableFutureList.add(SmartCompletableFuture.runAsync(() -> {
            CommonUtil.defaultList(starBasicDataMapper.selectBatchIds(starIdList))
                    .forEach(e -> starMap.putIfAbsent(e.getId(), e));
            CommonUtil.defaultList(starPlatformInfoMapper.selectBatchIds(starPlatformInfoIdList))
                    .forEach(e -> starPlatformMap.putIfAbsent(e.getId(), e));

        }));
        SmartCompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[]{})).join();
        //按照月份查询每天数据
        Map<Integer, List<DocIntentionOrder>> calendarMap = dataList.stream().filter(e -> Objects.nonNull(e.getPublishDate())).collect(Collectors.groupingBy(e -> DateUtil.dayOfMonth(e.getPublishDate())));
        List<Date> dayList = DateUtil.getAllDayOfMonth(searchDTO.getMonth());
        List<AnchorSchedulingCalendarVO.IntentionOrderCalendarSummary> calendarSummaryList = new ArrayList<>(dayList.size());
        Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
        dayList.forEach(day -> {
            AnchorSchedulingCalendarVO.IntentionOrderCalendarSummary calendarSummary = new AnchorSchedulingCalendarVO.IntentionOrderCalendarSummary();
            calendarSummary.setDay(day);
            int dayOfMonth = DateUtil.dayOfMonth(day);
            if(calendarMap.containsKey(dayOfMonth)) {
                calendarSummary.setIntentionOrderList(calendarMap.get(dayOfMonth).stream().map(intentionOrder ->
                        this.buildAnchorSchedulingCalendarVO(intentionOrder, starMap, customerMap, starPlatformMap, publishFormDictMap)).collect(Collectors.toList()));
            } else {
                calendarSummary.setIntentionOrderList(Collections.EMPTY_LIST);
            }
            calendarSummaryList.add(calendarSummary);
        });
        vo.setCalendarSummaryList(calendarSummaryList);
        return vo;
    }

    @Override
    public Page<AnchorSchedulingCalendarVO.IntentionOrderData> inquiryPage(AnchorSchedulingSearchDTO searchDTO) {
        searchDTO.setAlias("a.");
        Page<DocIntentionOrder> page = intentionOrderMapper.inquiryPage(new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize()), searchDTO);
        Page<AnchorSchedulingCalendarVO.IntentionOrderData> pageResult = new Page<>(page.getCurrent(), page.getSize(), page.getTotal(), page.isSearchCount());
        pageResult.setOptimizeCountSql(page.isOptimizeCountSql());
        pageResult.setCountId(page.getCountId());
        pageResult.setHitCount(page.isHitCount());
        pageResult.setMaxLimit(page.getMaxLimit());
        if(CollectionUtils.isNotEmpty(page.getRecords())) {
            List<Long> starIdList =  page.getRecords().stream().map(e -> e.getStarId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            List<Long> customerIdList =  page.getRecords().stream().map(e -> e.getCustomerId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            List<Long> starPlatformInfoIdList =  page.getRecords().stream().map(e -> e.getStarPlatformInfoId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            //查询客户数据
            Map<Long, BaseCustomer> customerMap = CommonUtil.defaultMap(baseInfoClient.getMcnCustomerByIds(customerIdList).getObj());
            //查询红人与红人平台数据
            Map<Long, StarBasicData> starMap = CommonUtil.defaultList(starBasicDataMapper.selectBatchIds(starIdList)).stream().collect(Collectors.toMap(StarBasicData::getId, Function.identity()));
            Map<Long, StarPlatformInfo> starPlatformMap = CommonUtil.defaultList(starPlatformInfoMapper.selectBatchIds(starPlatformInfoIdList)).stream().collect(Collectors.toMap(StarPlatformInfo::getId, Function.identity()));
            Map<String, String> publishFormDictMap = this.getPublishFormDictMap();
            pageResult.setRecords(page.getRecords().stream().map(intentionOrder ->
                    this.buildAnchorSchedulingCalendarVO(intentionOrder, starMap, customerMap, starPlatformMap, publishFormDictMap)).collect(Collectors.toList()));
        }
        return pageResult;
    }

    @Override
    public IntentionOrderStatusStatisVO getCountByStatus(IntentionOrderSearchDTO searchDTO) {
        return intentionOrderMapper.getCountByStatus(searchDTO);
    }

    @Override
    public List<String> getIntentionOrderCodes(Integer size, String likeCode,IntentionOrderSearchDTO searchDTO) {
        if (StringUtils.isBlank(likeCode)) {
            return null;
        }
        if (size == null) {
            size = 100;
        }
        return intentionOrderMapper.getIntentionOrderCodes(size, likeCode,searchDTO);
    }

    @Override
    public String getSplicedCodeFromQuestion(List<Long> idList) {
        List<DocIntentionOrderQuestion> dataList = intentionOrderQuestionMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrderQuestion.class)
                .in(DocIntentionOrderQuestion::getIntentionOrderId, idList)
                .eq(DocIntentionOrderQuestion::getIsDelete, NumberCst.ZERO));
        if(CollectionUtils.isEmpty(dataList)) {
            return null;
        }
        List<Long> intentionOrderIds = dataList.stream().map(DocIntentionOrderQuestion::getIntentionOrderId).distinct().collect(Collectors.toList());
        List<DocIntentionOrder> docIntentionOrderList = intentionOrderMapper.selectBatchIds(intentionOrderIds);
        if(CollectionUtils.isEmpty(docIntentionOrderList)) {
            return null;
        }
        return docIntentionOrderList.stream().map(DocIntentionOrder::getIntentionCode).collect(Collectors.joining(SeparatorCst.COMMA));
    }

    @Override
    public List<DocIntentionOrderQuestion> getQuestionsById(Long id) {
        return intentionOrderQuestionMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrderQuestion.class)
                .eq(DocIntentionOrderQuestion::getIntentionOrderId, id)
                .eq(DocIntentionOrderQuestion::getIsDelete, NumberCst.ZERO));
    }

    @Deprecated
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean acceptOrder(IntentionOrderAcceptDTO dto) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(dto.getId(), true);
        BusinessAssert.isFalse(IntentionOrderStatusEnum.INVALID.getCode().equals(docIntentionOrder.getStatus()),
                McnErrorCode.BUSINESS_ERROR, "该前置执行单已作废");
        BusinessAssert.isTrue(IntentionOrderStatusEnum.WAIT_ACCEPT.getCode().equals(docIntentionOrder.getStatus()),
                McnErrorCode.BUSINESS_ERROR, "非待接单状态-不允许接单");
        intentionOrderMapper.updateByNoStrategy(Wrappers.lambdaUpdate(DocIntentionOrder.class)
                .eq(DocIntentionOrder::getId, dto.getId())
                .set(DocIntentionOrder::getAcceptRemark, StringUtils.defaultString(dto.getAcceptRemark()))
                .set(DocIntentionOrder::getStatus, IntentionOrderStatusEnum.WAIT_LOCK.getCode())
                .set(DocIntentionOrder::getUpdateBy, UserVoContextHolder.getUserId())
                .set(DocIntentionOrder::getUpdateName, UserVoContextHolder.getUserName())
                .set(DocIntentionOrder::getUpdateDate, new Date()));
        if(CollectionUtils.isNotEmpty(dto.getAnswerList())) {
            dto.getAnswerList().forEach(e -> {
                DocIntentionOrderQuestion updateEntity = new DocIntentionOrderQuestion();
                updateEntity.setId(e.getQuestionId());
                updateEntity.setAnswer(StringUtils.defaultString(e.getAnswer()));
                intentionOrderQuestionMapper.updateById(updateEntity);
            });
        }
        //发送数据所有人已接单提醒
        this.sendMessage(docIntentionOrder, MsgCenterTemplateCst.INTENTION_ORDER_ACCEPTED, Arrays.asList(docIntentionOrder.getOwnerId()));
        return Boolean.TRUE;
    }

    /**
     * 获取前置执行单
     * @param id
     * @param verifyExist
     * @return
     */
    private DocIntentionOrder getDocIntentionOrder(Long id, boolean verifyExist) {
        DocIntentionOrder entity = intentionOrderMapper.selectOne(Wrappers.lambdaQuery(DocIntentionOrder.class)
                .eq(DocIntentionOrder::getId, id).eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO));
        if (verifyExist) {
            BusinessAssert.notNull(entity, McnErrorCode.DATA_NOT_FOUND, "该前置执行单不存在");
        }
        return entity;
    }

    /**
     * 校验保存参数
     * @param saveDTO
     */
    private void verifySaveParam(IntentionOrderSaveDTO saveDTO) {
        ValidatorUtil.validate(saveDTO, Modify.class);
        if(CommonUtil.greaterThanZero(saveDTO.getOtherIncomeAmount())) {
            BusinessAssert.notBlank(saveDTO.getOtherIncomeRemark(), McnErrorCode.PARAM_ERROR, "【其他加价收入说明】必填");
        }
        if(CommonUtil.greaterThanZero(saveDTO.getSpecialIncomeAmount())) {
            BusinessAssert.notBlank(saveDTO.getSpecialIncomeRemark(), McnErrorCode.PARAM_ERROR, "【机酒差旅补贴说明】必填");
        }
        if(CommonUtil.greaterThanZero(saveDTO.getSubsidyIncomeAmount())) {
            BusinessAssert.notBlank(saveDTO.getSubsidyIncomeRemark(), McnErrorCode.PARAM_ERROR, "【其他补贴性收入说明】必填");
        }
        if(NumberCst.ONE.equals(saveDTO.getHaveDiscountApproval())) {
            BusinessAssert.isTrue(StringUtils.isNotBlank(saveDTO.getDiscountScreenshot()), McnErrorCode.PARAM_ERROR, "折扣返点审批图片不能为空");
        }
    }

    /**
     *  获取刊例价
     * @param entity
     * @return
     */
    private BigDecimal getRateCardPrice(DocIntentionOrder entity) {
        RateCardPriceQueryDTO rateCardPriceQueryDTO = new RateCardPriceQueryDTO();
        rateCardPriceQueryDTO.setStarPlatformId(entity.getStarPlatformInfoId());
        rateCardPriceQueryDTO.setPublishDate(entity.getCreateDate());
        rateCardPriceQueryDTO.setPublishForm(entity.getPublishForm());
        return starRateCardService.getRateCardPrice(rateCardPriceQueryDTO);
    }

    /**
     *
     * @param intentionOrder
     * @param starMap
     * @param customerMap
     * @param starPlatformMap
     * @return
     */
    private AnchorSchedulingCalendarVO.IntentionOrderData buildAnchorSchedulingCalendarVO(DocIntentionOrder intentionOrder, Map<Long, StarBasicData> starMap, Map<Long, BaseCustomer> customerMap, Map<Long, StarPlatformInfo> starPlatformMap, Map<String, String> publishFormDictMap) {
        AnchorSchedulingCalendarVO.IntentionOrderData intentionOrderData = AnchorSchedulingCalendarVO.newIntentionOrderData();
        intentionOrderData.setId(intentionOrder.getId());
        intentionOrderData.setIntentionCode(intentionOrder.getIntentionCode());
        intentionOrderData.setPublishForm(intentionOrder.getPublishForm());
        intentionOrderData.setProductName(intentionOrder.getProductName());
        intentionOrderData.setPublishDate(intentionOrder.getPublishDate());
        if(customerMap.containsKey(intentionOrder.getCustomerId())) {
            BaseCustomer baseCustomer = customerMap.get(intentionOrder.getCustomerId());
            intentionOrderData.setCustomerName(StringUtils.defaultString(baseCustomer.getCustomerNameC()));
        }
        if(starPlatformMap.containsKey(intentionOrder.getStarPlatformInfoId())) {
            StarPlatformInfo starPlatformInfo = starPlatformMap.get(intentionOrder.getStarPlatformInfoId());
            intentionOrderData.setStarPlatformInfoId(intentionOrder.getStarPlatformInfoId());
            intentionOrderData.setPlatformId(starPlatformInfo.getPlatformId());
            intentionOrderData.setPlatformName(starPlatformInfo.getPlatformName());
            intentionOrderData.setPlatNickName(starPlatformInfo.getPlatNickName());
            intentionOrderData.setPublishForm(intentionOrder.getPublishForm());
            intentionOrderData.setPublishFormName(this.getPublishFormName(publishFormDictMap, starPlatformInfo.getPlatformId(), intentionOrder.getPublishForm()));
        }
        intentionOrderData.setStarId(intentionOrder.getStarId());
        if(starMap.containsKey(intentionOrder.getStarId())) {
            StarBasicData starBasicData = starMap.get(intentionOrder.getStarId());
            intentionOrderData.setStarNickName(StringUtils.defaultString(starBasicData.getStarNickname()));
        }
        intentionOrderData.setStatus(intentionOrder.getStatus());
        intentionOrderData.setStatusName(IntentionOrderStatusEnum.getStatusName(intentionOrder.getStatus()));
        intentionOrderData.setCardRatePrice(intentionOrder.getCardRatePrice());
        intentionOrderData.setOrderAmount(intentionOrder.getOrderAmount());
        intentionOrderData.setTotalIncomeAmount(intentionOrder.getTotalIncomeAmount());
        intentionOrderData.setRebate(intentionOrder.getRebate());
        intentionOrderData.setActualDiscountRatio(intentionOrder.getActualDiscountRatio());
        intentionOrderData.setCreateDate(intentionOrder.getCreateDate());
        return intentionOrderData;
    }

    /**
     * 发送消息
     * @param docIntentionOrder
     * @param msgCenterTemplate
     * @param targetUserIds
     */
    private void sendMessage(DocIntentionOrder docIntentionOrder, String msgCenterTemplate, List<Long> targetUserIds) {
        TransactionUtils.afterCommit(() -> {
            Map<String, String> param = new HashMap<>(16);
            param.put("code",docIntentionOrder.getIntentionCode());
            param.put("time", DateUtil.getTimeStr(docIntentionOrder.getPublishDate(), "yyyy-MM-dd"));
            param.put("productName", docIntentionOrder.getProductName());
            StarBasicData starBasicData = starBasicDataMapper.selectById(docIntentionOrder.getStarId());
            param.put("starName",starBasicData.getStarNickname());
            param.put("businessId",docIntentionOrder.getId().toString());
            messageSender.sendNotify(CommentBusinessTypeEnum.INTENTION_ORDER, UserVoContextHolder.getTenantId(), msgCenterTemplate, targetUserIds, param);
        });
    }

    /**
     * 获取发布平台字典Map
     * @return
     */
    private Map<String, String> getPublishFormDictMap() {
        List<BaseDictsVO> dictList = baseInfoClient.getSecondDictList(DictTypeCst.PUBLISHING_PLATFORM, false).getObj();
        Map<String, String> dictMap = new HashMap<>(16);
        if(CollectionUtils.isNotEmpty(dictList)) {
            for(BaseDictsVO baseDictsVO : dictList) {
                String dictsCode = baseDictsVO.getDictsCode();
                if(CollectionUtils.isEmpty(baseDictsVO.getThirdDictList())) {
                    continue;
                }
                baseDictsVO.getThirdDictList().forEach(t -> {
                    dictMap.put(StringUtils.joinWith(SeparatorCst.SEMICOLON, dictsCode, t.getSecondlevelCode()), t.getSecondlevelDictsNameC());
                });
            }
        }
        return dictMap;
    }

    /**
     * 获取发布形式名称
     * @param publishFormDictMap
     * @param platformId
     * @param publishForm
     * @return
     */
    private String getPublishFormName(Map<String, String> publishFormDictMap, String platformId, String publishForm) {
        if(MapUtils.isEmpty(publishFormDictMap) || StringUtils.isBlank(platformId) || StringUtils.isBlank(publishForm)) {
            return publishForm;
        }
        return publishFormDictMap.get(StringUtils.joinWith(SeparatorCst.SEMICOLON, platformId, publishForm));
    }

    /**
     * 初始化列表里面的发布形式名称信息
     *
     * @param starMap 红人信息MAP
     * @param records 记录信息
     */
    @Override
    public void initRecordPublishFormName(Map<Long, StarPlatInfoVO> starMap, List<ExcutionExportVO> records) {
        if (CollectionUtil.isEmpty(starMap) || CollectionUtil.isEmpty(records)) {
            return;
        }
        Map<String, String> map = getPublishFormDictMap();
        if (CollectionUtil.isEmpty(map)) {
            return;
        }
        records.forEach(value -> {
            StarPlatInfoVO starInfo = starMap.get(value.getStarPlatformInfoId());
            if (Objects.nonNull(starInfo)) {
                String publishFormName = getPublishFormName(map, starInfo.getPlatformId(), value.getPublishForm());
                value.setPublishForm(publishFormName);
            }
        });
    }

    @Override
    public IntentionOrderAmountSummaryVO getAmountSummary(IntentionOrderSearchDTO searchDTO) {
        return intentionOrderMapper.getAmountSummary(searchDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApprovalOperationVO changeApproval(ChangeApprovalDTO dto, Long billId) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(billId, true);
        BusinessAssert.isTrue(IntentionOrderStatusEnum.isAeLeaderConfirm(docIntentionOrder.getStatus()), "单据状态非待AE主管确认");
        ApprovalOperationVO approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), dto.getApprovalFlag(), dto.getRemark());
        BusinessAssert.isTrue(approvalOperationVO.isSuccess(), McnErrorCode.FLOW_ERROR, approvalOperationVO.getMessage());
        return approvalOperationVO;
    }

    /**
     * 审批流程并返回下一条
     * @param dto
     * @param billId 单据ID
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public NextNotifyVo changeApprovalNext(ChangeApprovalDTO dto, Long billId) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(billId, true);
        BusinessAssert.isTrue(IntentionOrderStatusEnum.isAeLeaderConfirm(docIntentionOrder.getStatus()), "单据状态非待AE主管确认");
        NextNotifyVo nextNotifyVo = approvalFlowService.approvalChangeNext(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), dto.getApprovalFlag(), dto.getRemark());
        return nextNotifyVo;
    }

    @Override
    public void approvalCallback(ApprovalFlowDTO approvalFlowDTO, Boolean status) {
        DocIntentionOrder docIntentionOrder = this.getDocIntentionOrder(approvalFlowDTO.getSrcId(), true);
        approvalFlowDTO.setSrcCode(docIntentionOrder.getIntentionCode());
        approvalFlowDTO.addSubmitInfoIfNull(docIntentionOrder);
        if (Objects.isNull(status)) {
            //审批流配置-接入待办
            return;
        }
        // 当主动撤回 作废时  不再去更新状态
        if (IntentionOrderStatusEnum.isAeLeaderConfirm(docIntentionOrder.getStatus())) {
            DocIntentionOrder updateEntity = new DocIntentionOrder();
            updateEntity.setId(docIntentionOrder.getId());
            updateEntity.setStatus(status ? IntentionOrderStatusEnum.CONRIMED.getCode() : IntentionOrderStatusEnum.REJECTED.getCode());
            intentionOrderMapper.updateById(updateEntity);
            //操作日志
            DocIntentionOrder before = new DocIntentionOrder();
            before.setId(docIntentionOrder.getId());
            before.setStatus(docIntentionOrder.getStatus());
            EventPublisher.post(OperateLogEvent.builder().businessId(docIntentionOrder.getId())
                    .businessType(LogBusinessTypeEnum.INTENTION_ORDER)
                    .compare(before, updateEntity)
                    .build());
        }
    }
}
